﻿using Clipper.Model.DataBaseModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Clipper.Model.DetectionModel
{
    /// <summary>
    /// 算法类
    /// </summary>
    public class AlgorithmClass
    {
        #region  //变量块
        private bool iSCheckSave = false;

        private string selectedValues = "";

        private int doTestCount;
        public int DoTestCount
        {
            get
            {
                return doTestCount;
            }
            set
            {
                doTestCount = value;
            }
        }

        public string SelectedValues
        {
            get
            {
                return selectedValues;
            }

            set
            {
                selectedValues = value;
            }
        }

        public bool ISCheckSave
        {
            get
            {
                return iSCheckSave;
            }

            set
            {
                iSCheckSave = value;
            }
        }
        #endregion

        /// <summary>
        /// 获取标准曲线的单条信息 浓度的集合
        /// </summary>
        /// <param name="standardCurve"></param>
        /// <returns></returns>
        public List<double> GetConcentrationList(StandardCurveData standardCurve)
        {
            List<double> concentrationList = new List<double>();  //浓度集合            
            if (standardCurve.Concentration1 != 0)
            {
                concentrationList.Add(standardCurve.Concentration1);
            }
            if (standardCurve.Concentration2 != 0)
            {
                concentrationList.Add(standardCurve.Concentration2);
            }
            if (standardCurve.Concentration3 != 0)
            {
                concentrationList.Add(standardCurve.Concentration3);
            }
            if (standardCurve.Concentration4 != 0)
            {
                concentrationList.Add(standardCurve.Concentration4);
            }
            if (standardCurve.Concentration5 != 0)
            {
                concentrationList.Add(standardCurve.Concentration5);
            }
            if (standardCurve.Concentration6 != 0)
            {
                concentrationList.Add(standardCurve.Concentration6);
            }
            return concentrationList;
        }

        /// <summary>
        /// 获取标准曲线的单条信息 浓度的集合  (log 对数)
        /// </summary>
        /// <param name="standardCurve"></param>
        /// <returns></returns>
        public List<double> GetConcentration_LogList(StandardCurveData standardCurve)
        {
            List<double> concentrationList = new List<double>();  //浓度集合            
            if (standardCurve.Concentration1 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration1));
            }
            if (standardCurve.Concentration2 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration2));
            }
            if (standardCurve.Concentration3 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration3));
            }
            if (standardCurve.Concentration4 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration4));
            }
            if (standardCurve.Concentration5 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration5));
            }
            if (standardCurve.Concentration6 != 0)
            {
                concentrationList.Add(Math.Log10(standardCurve.Concentration6));
            }
            return concentrationList;
        }

        /// <summary>
        /// 获取单条信息检测结果的集合
        /// </summary>
        /// <param name="standardCurve"></param>
        /// <returns></returns>
        public List<double> GetDetectResultList(StandardCurveData standardCurve)
        {
            List<double> detectResultList = new List<double>(); //检测结果集合
            if (standardCurve.DetectResult1 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult1);
            }
            if (standardCurve.DetectResult2 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult2);
            }
            if (standardCurve.DetectResult3 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult3);
            }
            if (standardCurve.DetectResult4 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult4);
            }
            if (standardCurve.DetectResult5 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult5);
            }
            if (standardCurve.DetectResult6 != 0)
            {
                detectResultList.Add(standardCurve.DetectResult6);
            }
            return detectResultList;
        }
        /// <summary>
        /// 获取单条信息检测结果的集合 (log  对数)
        /// </summary>
        /// <param name="standardCurve"></param>
        /// <returns></returns>
        public List<double> GetDetectResult_LogList(StandardCurveData standardCurve)
        {
            List<double> detectResultList = new List<double>(); //检测结果集合
            if (standardCurve.DetectResult1 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult1));
            }
            if (standardCurve.DetectResult2 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult2));
            }
            if (standardCurve.DetectResult3 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult3));
            }
            if (standardCurve.DetectResult4 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult4));
            }
            if (standardCurve.DetectResult5 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult5));
            }
            if (standardCurve.DetectResult6 != 0)
            {
                detectResultList.Add(Math.Log10(standardCurve.DetectResult6));
            }
            return detectResultList;
        }
        /// <summary>
        /// m_x是检测浓度 ，m_y是检测结果
        /// </summary>
        /// <param name="m_x"></param>
        /// <param name="m_y"></param>
        /// <returns></returns>
        /// 
        double xAverage = 0; // x的平均数
        double yAverage = 0;  // y的平均数
        public double getLineValue(List<double> m_x, List<double> m_y) //  m_x是检测浓度 ，m_y是检测结果
        {

            double X = 0;
            foreach (double concentration in m_x)
            {
                X += concentration;
            }

            double y = 0;
            foreach (double detectResult in m_y)
            {
                y += detectResult;  //检测结果集合
            }
            xAverage = X / m_y.Count;  // x的平均数
            yAverage = y / m_y.Count;  // y的平均数

            double countResult = 0; //表达式上面的结果
            double reagentGan = 0;  //表达式下面的结果
            double yreagentGan = 0;
            for (int i = 0; i < m_y.Count; i++)
            {
                countResult += (m_x[i] - xAverage) * (m_y[i] - yAverage);
                reagentGan += Math.Pow((m_x[i] - xAverage), 2);
                yreagentGan += Math.Pow((m_y[i] - yAverage), 2);
            }
            return Math.Pow((countResult / Math.Sqrt(reagentGan * yreagentGan)), 2);

            //int r =∑(Xi - X的平均数)(Yi - Y平均数) / 根号下[∑(Xi - X平均数) ^ 2 *∑(Yi - Y平均数) ^ 2]
        }


        /// <summary>
        /// 计算系数b的值
        /// </summary>
        /// <param name="m_x"></param>
        /// <param name="m_y"></param>
        /// <returns></returns>
        public List<double> setCoefficientB(List<double> m_x, List<double> m_y) //m_x是检测浓度集合 ，m_y是检测结果集合
        {
            List<double> resultList = new List<double>();

            double X = 0;
            foreach (double concentration in m_x)
            {
                X += concentration;
            }

            double y = 0;
            foreach (double detectResult in m_y)
            {
                y += detectResult;  //检测结果集合
            }
            double xAverage = X / m_y.Count;  // x的平均数
            double yAverage = y / m_y.Count;  // y的平均数
            resultList.Add(xAverage);
            resultList.Add(yAverage);

            double topCount = 0;
            double bottomCount = 0;
            for (int j = 0; j < m_x.Count; j++)
            {
                topCount += (m_x[j] - xAverage) * (m_y[j] - yAverage);
                bottomCount += Math.Pow((m_x[j] - xAverage), 2);
            }
            resultList.Add(Math.Round((topCount / bottomCount), 3));
            return resultList;
        }

        /// <summary>
        /// 获取浓度或活性
        /// </summary>
        /// <returns></returns>
        /// 
        List<double> concentrationList;
        List<double> detectResultList;

        public string getActivityValue(StandardCurveData standardCurve, string detectVlaue, int varietyID)
        {
            string activityVlaue = ""; //声明活性值
            if (varietyID == 1)
            {
                concentrationList = GetConcentration_LogList(standardCurve);  //浓度集合            
                detectResultList = GetDetectResult_LogList(standardCurve); //检测结果集合
            }
            else if (varietyID == 2)
            {
                concentrationList = GetConcentrationList(standardCurve);  //浓度集合            
                detectResultList = GetDetectResultList(standardCurve); //检测结果集合
            }

            double k = 0.00; //斜率
            double b = 0.00;
            if (!detectVlaue.Equals("") || detectVlaue != null)
            {
                double txtValue;
                if (varietyID == 1)
                   txtValue  = Math.Log10(Convert.ToDouble(detectVlaue));
                  //  return "0";
                else
                    txtValue = Convert.ToDouble(detectVlaue);

                if (detectResultList.Max() <= txtValue)
                {
                    k = (detectResultList[detectResultList.Count - 1] - detectResultList[detectResultList.Count - 2]) / (concentrationList[concentrationList.Count - 1] - concentrationList[concentrationList.Count - 2]);
                    b = detectResultList[detectResultList.Count - 1] - k * concentrationList[concentrationList.Count - 1];
                    activityVlaue = ((txtValue - b) / k).ToString("#.##");

                }
                else if (detectResultList.Min() >= txtValue)
                {
                    k = (detectResultList[1] - detectResultList[0]) / (concentrationList[1] - concentrationList[0]);
                    b = detectResultList[1] - k * concentrationList[1];
                    activityVlaue = ((txtValue - b) / k).ToString("#.##");

                }
                else
                {
                    for (int i = 0; i < detectResultList.Count; i++)
                    {
                        if (detectResultList[i] < txtValue && txtValue <= detectResultList[i + 1] ||
                            detectResultList[i] > txtValue && txtValue >= detectResultList[i + 1])
                        {
                            k = Convert.ToDouble((detectResultList[i + 1] - detectResultList[i]) / (concentrationList[i + 1] - concentrationList[i]));
                            b = detectResultList[i] - k * concentrationList[i];
                            activityVlaue = ((txtValue - b) / k).ToString("#.##");
                            break;
                        }
                    }
                }
            }
            if (varietyID == 1)
                activityVlaue = Math.Pow(10,Convert.ToDouble(activityVlaue)).ToString("#.##");
            return activityVlaue;
        }

        /// <summary>
        /// 计算DD的值 时间点中值的id
        /// </summary>
        /// <param name="data"></param>
        /// <param name="backNum"></param>
        /// <returns></returns>
        public  double GetOD(ObservableCollection<int> datain, ObservableCollection<int> timein)
        {

            ObservableCollection<int> data = new ObservableCollection<int>();//--------
            data = datain;
            int ddStart = 800;
            int ddEnd = 1200;
            data = GetMedienSmoothOptData(data, 2, 2);   //中值平滑点
            data = GetShiftAveSmoothOptData(data, 2, 2); //平均值平滑


            double myOd = ((double)(data[ddEnd] - data[ddStart]) /
                    (double)((timein[ddEnd] - timein[ddStart]) / 1000.0f));//------------
            //int tempdata = data[backNum + 1];//--------------------------
            //for (int i = 0; i < backNum + 1; i++) //试剂添加抖动处理
            //{
            //    data[i] = tempdata;
            //}

            //for (int i = 0; i < data.Count; i++) //试剂添加抖动处理
            //{
            //    data[i] = tempdata - data[i];
            //}
            //int Maxdata = data.Max();
            //int Mindata = data.Min();
            //int avageData = (Maxdata - Mindata) / 2;
            ////寻找最接近中值的数据序号，作为时间轴
            //int resultIndex = 0;
            //for (int i = 0; i < data.Count; i++)
            //{
            //    if (data[i] > avageData) //找到第一个大于avageData的点
            //    {
            //        resultIndex = i;
            //        break;
            //    }
            //}//---------------------------------
            //if (resultIndex > 500)
            //{
            //    double myOd = (double)(data[resultIndex + 500] - data[resultIndex - 500]) / 40.0;
            //    return myOd;
            //  }
            // = data.IndexOf((Maxdata - Mindata)/2);

            return myOd;
        }

        /// <summary>
        /// 计算除DD以外的 时间点中值的id
        /// </summary>
        /// <param name="data"></param>
        /// <param name="backNum"></param>
        /// <returns></returns>
        public int GetSec(ObservableCollection<int> data, int backNum)
        {
            int tempdata = data[backNum + 1];

            for (int i = 0; i < backNum + 1; i++) //试剂添加抖动处理
            {
                data[i] = tempdata;
            }

            for (int i = 0; i < data.Count; i++) //试剂添加抖动处理
            {
                data[i] = tempdata - data[i];
            }

            data = GetMedienSmoothOptData(data, 2, 2);   //中值平滑点
            data = GetShiftAveSmoothOptData(data, 2, 2); //平均值平滑


            int Maxdata = data.Max();
            int Mindata = data.Min();
            int avageData = (Maxdata - Mindata) / 2 + Mindata;
            //寻找最接近中值的数据序号，作为时间轴
            int resultIndex = 0;
            for (int i = 0; i < data.Count; i++)
            {
                if (data[i] > avageData) //找到第一个大于avageData的点
                {
                    resultIndex = i;
                    break;
                }
            }
            // = data.IndexOf((Maxdata - Mindata)/2);

            return resultIndex;
        }

        public static ObservableCollection<int> GetMedienSmoothOptData(ObservableCollection<int> optData, int before_p, int after_p)
        {
            ObservableCollection<int> numArray = new ObservableCollection<int>();
            int index = 0;
            int num2 = (before_p + 1) + after_p;
            double[] array = new double[num2];
            double num3 = 0.0;
            for (int i = 0; i < optData.Count; i++)
            {
                if (((num2 > 1) && (i >= before_p)) && (i < (optData.Count - after_p)))
                {
                    index = 0;
                    for (int j = i - before_p; j <= (i + after_p); j++)
                    {
                        array[index] = optData[j];
                        index++;
                    }
                    Array.Sort<double>(array);
                    num3 = array[index / 2];
                }
                else
                {
                    num3 = optData[i];
                }
                numArray.Add((int)num3);
            }
            return numArray;
        }
        public static ObservableCollection<int> GetShiftAveSmoothOptData(ObservableCollection<int> optData, int before_p, int after_p)
        {
            ObservableCollection<int> numArray = new ObservableCollection<int>();
            int num = (before_p + 1) + after_p;
            int num2 = 0;
            for (int i = 0; i < optData.Count; i++)
            {
                if (((num > 1) && (i >= before_p)) && (i < (optData.Count - after_p)))
                {
                    num2 = 0;
                    for (int j = i - before_p; j <= (i + after_p); j++)
                    {
                        num2 += optData[j];
                    }
                    numArray.Add((int)(num2 / num));
                }
                else
                {
                    numArray.Add(optData[i]);
                }
            }
            return numArray;
        }
    }
}
